//增量实现undo和redo(已弃用,改用全量)

import { fabric } from 'fabric';

// 1. 定义命令接口和基础类
class CanvasCommand {
    constructor(canvas) {
        this.canvas = canvas;
    }

    // 所有子类必须实现这些方法
    execute() {
        throw new Error('需要子类实现');
    }

    undo() {
        throw new Error('需要子类实现');
    }

    redo() {
        throw new Error('需要子类实现');
    }

    serialize() {
        return {
            type: this.constructor.name
        };
    }
}

// 添加对象命令
class AddObjectCommand extends CanvasCommand {
    constructor(canvas, object) {
        super(canvas);
        this.objectData = object.toJSON(['id']);
        this.objectId = object.id;

        // 确保有可用的ID
        if (!this.objectId) {
            this.objectId = `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
            this.objectData.id = this.objectId;
        }

        // 保存对象的原始引用
        this.originalObject = object;
        console.log(`创建添加命令，ID=${this.objectId}`);
    }

    async execute() {
        try {
            // 先检查是否已存在相同ID的对象，如果有则删除
            const existingObj = this._findObjectById(this.objectId);
            if (existingObj) {
                // 直接调用canvas.remove以避免触发额外事件
                const objIndex = this.canvas._objects.indexOf(existingObj);
                if (objIndex > -1) {
                    this.canvas._objects.splice(objIndex, 1);
                }
            }

            // 如果有原始对象引用并且它有canvas属性，直接使用它
            if (this.originalObject && this.originalObject.canvas === this.canvas) {
                console.log(`使用原始对象添加: ID=${this.objectId}`);

                // 确保对象有正确的ID
                if (!this.originalObject.id) {
                    this.originalObject.id = this.objectId;
                }

                // 标记此对象为命令添加，防止事件循环
                this.originalObject._commandProcessed = true;

                // 手动添加到_objects数组，避免触发事件
                if (!this.canvas._objects.includes(this.originalObject)) {
                    this.canvas._objects.push(this.originalObject);
                }

                this.originalObject.setCoords();
                this.canvas.requestRenderAll();
                console.log(`执行添加命令完成: ID=${this.objectId}`);
                return true;
            }

            // 创建新对象，但先不添加到画布
            const obj = await new Promise((resolve, reject) => {
                fabric.util.enlivenObjects([this.objectData], (objects) => {
                    if (objects && objects.length > 0) {
                        resolve(objects[0]);
                    } else {
                        reject(new Error('Failed to create object'));
                    }
                });
            });

            // 确保对象有正确的ID和canvas引用
            obj.id = this.objectId;
            obj.canvas = this.canvas;

            // 标记此对象为命令添加，防止事件循环
            obj._commandProcessed = true;

            // 手动添加到_objects数组，避免触发事件
            this.canvas._objects.push(obj);
            obj.setCoords();

            // 保存新创建的对象引用
            this.originalObject = obj;

            // 手动请求渲染
            this.canvas.requestRenderAll();
            console.log(`执行添加命令完成: ID=${this.objectId}`);
            return true;
        } catch (error) {
            console.error('执行添加命令出错:', error);
            return false;
        }
    }

    async undo() {
        try {
            console.log(`开始撤销添加命令: ID=${this.objectId}`);

            // 先尝试使用原始对象引用
            let objToRemove = this.originalObject;

            // 如果原始对象无效，通过ID查找
            if (!objToRemove || objToRemove.canvas !== this.canvas) {
                objToRemove = this._findObjectById(this.objectId);
            }

            if (objToRemove) {
                console.log(`找到要撤销的对象: ID=${this.objectId}`);

                // 直接从_objects数组移除，避免触发事件
                const objIndex = this.canvas._objects.indexOf(objToRemove);
                if (objIndex > -1) {
                    this.canvas._objects.splice(objIndex, 1);
                    console.log(`已从画布移除对象: ID=${this.objectId}`);
                } else {
                    console.warn(`对象不在画布对象列表中: ID=${this.objectId}`);
                }

                this.canvas.requestRenderAll();
                console.log(`撤销添加命令完成: ID=${this.objectId}`);
                return true;
            } else {
                console.warn(`找不到要撤销的对象: ID=${this.objectId}`);
                return false;
            }
        } catch (error) {
            console.error('撤销添加命令出错:', error);
            return false;
        }
    }

    _findObjectById(id) {
        if (!id) {
            console.warn('查找对象时ID为空');
            return null;
        }

        // 获取所有非光标对象
        const objects = this.canvas
            .getObjects()
            .filter((obj) => obj.type !== 'cursor' && !obj.id?.includes('cursor'));

        const obj = objects.find((obj) => obj.id === id);
        if (!obj) {
            console.log(`在画布上未找到ID=${id}的对象`);
            // 输出当前画布上的所有对象ID供调试
            const objectIds = objects.map((o) => o.id).join(', ');
            console.log(`当前画布对象ID: [${objectIds}]`);
        }
        return obj;
    }

    async redo() {
        return this.execute();
    }

    serialize() {
        return {
            ...super.serialize(),
            objectId: this.objectId,
            objectData: this.objectData
        };
    }
}

// 修改对象命令
class ModifyObjectCommand extends CanvasCommand {
    constructor(canvas, objectId, newState, oldState) {
        super(canvas);
        this.objectId = objectId;
        this.newState = newState;
        this.oldState = oldState;
    }

    async execute() {
        try {
            const obj = this._findObjectById(this.objectId);
            if (!obj) {
                console.warn(`找不到要修改的对象: ID=${this.objectId}`);
                return false;
            }

            // 保存旧状态
            if (!this.oldState) {
                this.oldState = obj.toJSON(['id']);
            }

            // 应用新状态
            obj.set(this.newState);
            obj.setCoords();
            this.canvas.requestRenderAll();
            return true;
        } catch (error) {
            console.error('执行修改命令时出错:', error);
            return false;
        }
    }

    async undo() {
        try {
            const obj = this._findObjectById(this.objectId);
            if (!obj) {
                console.warn(`找不到要撤销修改的对象: ID=${this.objectId}`);
                return false;
            }

            // 保存当前状态用于重做
            this.newState = obj.toJSON(['id']);

            // 应用旧状态
            obj.set(this.oldState);
            obj.setCoords();

            // 强制更新画布
            this.canvas.requestRenderAll();

            return true;
        } catch (error) {
            console.error('撤销修改命令时出错:', error);
            return false;
        }
    }

    async redo() {
        try {
            const obj = this._findObjectById(this.objectId);
            if (!obj) {
                console.warn(`找不到要重做修改的对象: ID=${this.objectId}`);
                return false;
            }

            // 应用新状态
            obj.set(this.newState);
            obj.setCoords();

            // 强制更新画布
            this.canvas.requestRenderAll();

            return true;
        } catch (error) {
            console.error('重做修改命令时出错:', error);
            return false;
        }
    }

    _findObjectById(id) {
        // 获取所有非光标对象
        const objects = this.canvas
            .getObjects()
            .filter((obj) => obj.type !== 'cursor' && !obj.id?.includes('cursor'));
        return objects.find((obj) => obj.id === id);
    }

    serialize() {
        return {
            type: this.constructor.name,
            objectId: this.objectId,
            newState: this.newState,
            oldState: this.oldState
        };
    }
}

// 删除对象命令
class DeleteObjectCommand extends CanvasCommand {
    constructor(canvas, objectId) {
        super(canvas);
        this.objectId = objectId;
        this.objectData = null;

        // 在构造时立即保存对象状态
        const obj = this._findObjectById(objectId);
        if (obj) {
            this.objectData = obj.toJSON(['id']);
        }
    }

    execute() {
        return new Promise((resolve, reject) => {
            try {
                const obj = this._findObjectById(this.objectId);
                if (obj) {
                    // 确保保存对象状态
                    if (!this.objectData) {
                        this.objectData = obj.toJSON(['id']);
                    }
                    console.log(`执行删除命令: ID=${this.objectId}`);
                    this.canvas.remove(obj);
                    this.canvas.requestRenderAll();
                } else {
                    console.warn(`找不到要删除的对象: ID=${this.objectId}`);
                }
                resolve(this);
            } catch (error) {
                console.error('执行删除命令出错:', error);
                reject(error);
            }
        });
    }

    undo() {
        return new Promise((resolve, reject) => {
            try {
                if (this.objectData) {
                    fabric.util.enlivenObjects([this.objectData], (objects) => {
                        const obj = objects[0];
                        obj.canvas = this.canvas;
                        this.canvas.add(obj);
                        obj.setCoords();
                        this.canvas.requestRenderAll();
                        console.log(`撤销删除命令: ID=${this.objectId}`);
                        resolve(this);
                    });
                } else {
                    console.warn(`没有保存的对象数据: ID=${this.objectId}`);
                    resolve(this);
                }
            } catch (error) {
                console.error('撤销删除命令出错:', error);
                reject(error);
            }
        });
    }

    redo() {
        return new Promise((resolve, reject) => {
            try {
                const obj = this._findObjectById(this.objectId);
                if (obj) {
                    console.log(`重做删除命令: ID=${this.objectId}`);
                    this.canvas.remove(obj);
                    this.canvas.requestRenderAll();
                } else {
                    console.warn(`找不到要重做删除的对象: ID=${this.objectId}`);
                }
                resolve(this);
            } catch (error) {
                console.error('重做删除命令出错:', error);
                reject(error);
            }
        });
    }

    _findObjectById(id) {
        // 获取所有非光标对象
        const objects = this.canvas
            .getObjects()
            .filter((obj) => obj.type !== 'cursor' && !obj.id?.includes('cursor'));
        return objects.find((obj) => obj.id === id);
    }

    serialize() {
        return {
            ...super.serialize(),
            objectId: this.objectId,
            objectData: this.objectData
        };
    }
}

// 命令管理器
class CommandManager {
    constructor(canvas, collaborationRef) {
        this.canvas = canvas;
        this.collaborationRef = collaborationRef;
        this.undoStack = [];
        this.redoStack = [];
        this.maxStackSize = 50;
        this.isExecutingCommand = false; // 添加标记，避免重复执行
        this.isUndoRedoOperation = false; // 添加标记，标识当前是否为撤销/重做操作
    }

    // 过滤命令栈，确保只有非光标对象的命令
    _filterCursorCommands(commandStack) {
        return commandStack.filter((command) => {
            // 检查命令是否与光标对象相关
            if (
                command.objectId &&
                (command.objectId.includes('cursor') ||
                    (command.objectData && command.objectData.type === 'cursor'))
            ) {
                console.log(`过滤掉光标命令: ${command.constructor.name}, ID=${command.objectId}`);
                return false;
            }
            return true;
        });
    }

    async executeCommand(command) {
        // 忽略光标相关命令
        if (
            command.objectId &&
            (command.objectId.includes('cursor') ||
                (command.objectData && command.objectData.type === 'cursor'))
        ) {
            console.log(`忽略光标命令: ${command.constructor.name}, ID=${command.objectId}`);
            return false;
        }

        // 如果已经在执行命令中，不再重复执行
        if (this.isExecutingCommand) {
            console.warn('正在执行其他命令，跳过');
            return false;
        }

        try {
            this.isExecutingCommand = true;
            console.log(`执行命令: ${command.constructor.name}`);
            const success = await command.execute();

            if (success) {
                // 添加到撤销栈
                this.undoStack.push(command);

                // 如果不是撤销/重做操作，则清空重做栈
                if (!this.isUndoRedoOperation) {
                    if (this.redoStack.length > 0) {
                        console.log('执行新操作，清空重做栈');
                        this.redoStack = [];
                    }
                }

                // 限制栈大小
                if (this.undoStack.length > this.maxStackSize) {
                    this.undoStack.shift();
                }

                console.log(
                    `命令执行完成，撤销栈大小: ${this.undoStack.length}, 重做栈大小: ${this.redoStack.length}`
                );

                // 发送到远程
                if (this.collaborationRef?.wsProvider) {
                    this.collaborationRef.wsProvider.awareness.setLocalStateField('canvasCommand', {
                        type: 'command:execute',
                        command: command.serialize(),
                        timestamp: Date.now()
                    });
                }

                // 强制更新画布
                this.canvas.requestRenderAll();
                return true;
            }
            return false;
        } catch (error) {
            console.error('执行命令时出错:', error);
            return false;
        } finally {
            this.isExecutingCommand = false;
            this.isUndoRedoOperation = false; // 重置标志
        }
    }

    async undo() {
        if (this.undoStack.length === 0) {
            console.log('无法执行撤销，撤销栈为空');
            return;
        }

        // 如果已经在执行命令中，不再重复执行
        if (this.isExecutingCommand) {
            console.warn('正在执行其他命令，跳过撤销');
            return;
        }

        try {
            this.isExecutingCommand = true;
            this.isUndoRedoOperation = true; // 标记为撤销操作

            // 查找第一个非光标对象的命令
            let commandIndex = this.undoStack.length - 1;
            let command = this.undoStack[commandIndex];

            while (
                commandIndex >= 0 &&
                command &&
                ((command.objectId && command.objectId.includes('cursor')) ||
                    (command.objectData && command.objectData.type === 'cursor'))
            ) {
                console.log(
                    `跳过光标命令: ${command.constructor.name}, ID=${command.objectId || '未知'}`
                );
                commandIndex--;
                command = commandIndex >= 0 ? this.undoStack[commandIndex] : null;
            }

            if (!command) {
                console.log('没有找到可撤销的非光标命令');
                return;
            }

            // 移除该命令
            this.undoStack.splice(commandIndex, 1);

            console.log(`执行撤销: ${command.constructor.name}, ID=${command.objectId || '未知'}`);

            const success = await command.undo();
            if (!success) {
                console.warn('撤销操作失败，命令将保留在撤销栈中');
                // 将命令放回撤销栈
                this.undoStack.push(command);
                return;
            }

            this.redoStack.push(command);

            // 发送到远程
            if (this.collaborationRef?.wsProvider) {
                this.collaborationRef.wsProvider.awareness.setLocalStateField('canvasCommand', {
                    type: 'command:undo',
                    command: command.serialize(),
                    timestamp: Date.now()
                });
            }

            console.log(
                `撤销完成，撤销栈大小: ${this.undoStack.length}, 重做栈大小: ${this.redoStack.length}`
            );

            // 强制更新画布
            this.canvas.requestRenderAll();
        } catch (error) {
            console.error('执行撤销时出错:', error);
        } finally {
            this.isExecutingCommand = false;
            this.isUndoRedoOperation = false; // 重置标志
        }
    }

    async redo() {
        if (this.redoStack.length === 0) {
            console.log('无法执行重做，重做栈为空');
            return;
        }

        // 如果已经在执行命令中，不再重复执行
        if (this.isExecutingCommand) {
            console.warn('正在执行其他命令，跳过重做');
            return;
        }

        try {
            this.isExecutingCommand = true;
            this.isUndoRedoOperation = true; // 标记为重做操作

            // 查找第一个非光标对象的命令
            let commandIndex = this.redoStack.length - 1;
            let command = this.redoStack[commandIndex];

            while (
                commandIndex >= 0 &&
                command &&
                ((command.objectId && command.objectId.includes('cursor')) ||
                    (command.objectData && command.objectData.type === 'cursor'))
            ) {
                console.log(
                    `跳过光标命令: ${command.constructor.name}, ID=${command.objectId || '未知'}`
                );
                commandIndex--;
                command = commandIndex >= 0 ? this.redoStack[commandIndex] : null;
            }

            if (!command) {
                console.log('没有找到可重做的非光标命令');
                return;
            }

            // 移除该命令
            this.redoStack.splice(commandIndex, 1);

            console.log(`执行重做: ${command.constructor.name}, ID=${command.objectId || '未知'}`);

            const success = await command.redo();
            if (!success) {
                console.warn('重做操作失败，命令将保留在重做栈中');
                this.redoStack.push(command);
                return;
            }

            this.undoStack.push(command);

            // 发送到远程
            if (this.collaborationRef?.wsProvider) {
                this.collaborationRef.wsProvider.awareness.setLocalStateField('canvasCommand', {
                    type: 'command:redo',
                    command: command.serialize(),
                    timestamp: Date.now()
                });
            }

            console.log(
                `重做完成，撤销栈大小: ${this.undoStack.length}, 重做栈大小: ${this.redoStack.length}`
            );

            // 强制更新画布
            this.canvas.requestRenderAll();
        } catch (error) {
            console.error('执行重做时出错:', error);
        } finally {
            this.isExecutingCommand = false;
            this.isUndoRedoOperation = false; // 重置标志
        }
    }

    createAddCommand(object) {
        if (!object || !this.canvas) {
            console.warn('创建添加命令失败：对象或画布为空');
            return null;
        }
        console.log('创建添加命令:', object.id);
        return new AddObjectCommand(this.canvas, object);
    }

    createModifyCommand(object, oldState) {
        if (!object || !this.canvas) return null;
        return new ModifyObjectCommand(this.canvas, object.id, object.toJSON(['id']), oldState);
    }

    createDeleteCommand(objectId) {
        if (!objectId || !this.canvas) return null;
        return new DeleteObjectCommand(this.canvas, objectId);
    }
}

// 导出类
export {
    CanvasCommand,
    AddObjectCommand,
    ModifyObjectCommand,
    DeleteObjectCommand,
    CommandManager
};
